package config

import (
	"fmt"
	"go-pan/internal/log"
	"os"
	"strings"

	"github.com/spf13/viper"
	"go.uber.org/zap"
)

var (
	// Cfg 全局配置实例
	Cfg *AppConfig
)

// InitViper 初始化Viper配置
// env: 环境名称 (dev, test, prod)，默认从环境变量 APP_ENV 读取，如果未设置则使用 dev
func InitViper() (*AppConfig, error) {
	// 获取环境变量（可通过 APP_ENV 指定环境）
	env := os.Getenv("APP_ENV")
	if env == "" {
		env = "dev"
	}

	viper.SetConfigName("config") // 配置文件名称（不含扩展名）
	viper.SetConfigType("yaml")   // 配置文件类型

	// 设置配置文件搜索路径
	viper.AddConfigPath("./config")  // 当前目录下的config文件夹
	viper.AddConfigPath(".")         // 当前目录
	viper.AddConfigPath("../config") // 上一级目录的config文件夹

	// 根据环境加载对应的配置文件
	if env != "" {
		viper.SetConfigName(fmt.Sprintf("config.%s", env))
		// 如果指定环境的配置文件不存在，尝试加载默认配置
		if err := viper.ReadInConfig(); err != nil {
			// 回退到默认配置文件
			viper.SetConfigName("config")
			if err := viper.ReadInConfig(); err != nil {
				return nil, fmt.Errorf("failed to read config file: %w", err)
			}
		}
	} else {
		if err := viper.ReadInConfig(); err != nil {
			return nil, fmt.Errorf("failed to read config file: %w", err)
		}
	}

	// 支持环境变量覆盖配置
	// 格式：APP_SERVER_HOST, APP_DATABASE_HOST 等
	viper.SetEnvPrefix("APP")
	viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
	viper.AutomaticEnv() // 自动读取环境变量

	// 将配置读取到结构体
	var cfg AppConfig
	if err := viper.Unmarshal(&cfg); err != nil {
		return nil, fmt.Errorf("failed to unmarshal config: %w", err)
	}

	// 处理环境变量替换（对于prod配置中的 ${VAR:default} 格式）
	// 注意：viper本身不支持这种格式，我们需要手动处理
	if env == "prod" {
		// 生产环境可能需要手动处理环境变量替换
		// 这里简化处理，直接通过环境变量覆盖即可
	}

	Cfg = &cfg
	return &cfg, nil
}

// GetConfig 获取配置（需要先调用InitViper）
func GetConfig() *AppConfig {
	if Cfg == nil {
		panic("config not initialized, please call InitViper first")
	}
	return Cfg
}

// GetDSN 获取数据库连接字符串
func GetDSN() string {
	db := Cfg.Database
	// 支持从环境变量覆盖
	host := os.Getenv("DB_HOST")
	if host == "" {
		host = db.Host
	}
	user := os.Getenv("DB_USER")
	if user == "" {
		user = db.User
	}
	password := os.Getenv("DB_PASSWORD")
	if password == "" {
		password = db.Password
	}
	dbname := os.Getenv("DB_NAME")
	if dbname == "" {
		dbname = db.DBName
	}
	port := db.Port
	if p := os.Getenv("DB_PORT"); p != "" {
		fmt.Sscanf(p, "%d", &port)
	}

	return fmt.Sprintf("host=%s user=%s password=%s dbname=%s port=%d sslmode=%s TimeZone=%s",
		host, user, password, dbname, port, db.SSLMode, db.TimeZone)
}

// Init 初始化配置和数据库
func Init() {
	var err error

	// 获取环境变量（可通过 APP_ENV 指定环境）
	env := os.Getenv("APP_ENV")
	if env == "" {
		env = "dev"
	}

	// 初始化Viper配置
	Cfg, err = InitViper()
	if err != nil {
		// 如果还没有日志系统，使用panic
		if SystemLogger == nil {
			panic("failed to initialize config: " + err.Error())
		}
		SystemLogger.Fatal("failed to initialize config", zap.Error(err))
		return
	}

	// 初始化日志系统（需要在数据库初始化之前）
	logConfig := &log.LogConfig{
		Level:         Cfg.Log.Level,
		ToFile:        Cfg.Log.ToFile,
		Development:   Cfg.Log.Development,
		AccessLogPath: Cfg.Log.AccessLogPath,
		BizLogPath:    Cfg.Log.BizLogPath,
		AuditLogPath:  Cfg.Log.AuditLogPath,
		SystemLogPath: Cfg.Log.SystemLogPath,
		DebugLogPath:  Cfg.Log.DebugLogPath,
		AuthLogPath:   Cfg.Log.AuthLogPath,
	}

	SystemLogger, err = log.InitLogger(logConfig)
	if err != nil {
		panic("failed to initialize log: " + err.Error())
	}

	// 初始化数据库
	InitDatabase()

	// 记录配置加载成功
	SystemLogger.Info("configuration loaded",
		zap.String("env", env),
		zap.String("config_file", viper.ConfigFileUsed()))
}
